package hardware;

import java.util.LinkedList;

public class RegisterMap {

	static LinkedList<Register> tempRegs;
	static LinkedList<Rename> renamedRegs;

	public RegisterMap() {
		tempRegs = new LinkedList<Register>();
		renamedRegs = new LinkedList<Rename>();
		for (int i = 8; i <= 20; i++) {
			Register r = new Register("R" + "" + i, 0);
			tempRegs.add(r);
		}
	}

	// renames the register
	public static Register rename(Register reg) {
		if (reg == null)
			return null;
		if (tempRegs.size() > 0) {
			Register rename = tempRegs.removeFirst();
			for (int i = 0; i < renamedRegs.size(); i++) {
				if (reg.equals(renamedRegs.get(i).original)) {
					Rename re = new Rename(reg, rename);
					// tempRegs.add(renamedRegs.remove(i).renamed);
					renamedRegs.remove(i);
					renamedRegs.addLast(re);
					return rename;
				}
			}
			Rename re = new Rename(reg, rename);
			renamedRegs.addLast(re);
			return rename;
		} else {
			return null;
		}
	}

	/**
	 * free renamed register with it's orignal register (logical register)
	 * equals to reg.
	 * 
	 * @param reg
	 *            reg that i want to check with it.
	 */
	public static void freeRenamed(Register reg) {
		for (int i = 0; i < renamedRegs.size(); i++) {
			if (renamedRegs.get(i).original.equals(reg)) {
				Register r = renamedRegs.get(i).renamed;
				renamedRegs.remove(i);
				tempRegs.addLast(r);
				break;
			}
		}

	}

	/**
	 * gets the renamed register given the original register
	 * 
	 * @param orig
	 *            original register that i want to check with it.
	 * @return the renamed register.
	 */
	public static Register getRenamed(Register orig) {
		for (int i = 0; i < renamedRegs.size(); i++) {
			if (renamedRegs.get(i).original.name.equals(orig.name)) {
				return renamedRegs.get(i).renamed;
			}
		}
		return orig;
	}

	/**
	 * gets the original register given the renamed one
	 * 
	 * @param reg
	 *            renamed register that i want to check with it.
	 * @return the original register.
	 */
	public static Register getOriginal(Register reg) {
		for (int i = 0; i < renamedRegs.size(); i++) {
			if (reg.equals(renamedRegs.get(i).renamed)) {
				return renamedRegs.get(i).original;
			}
		}
		return reg;
	}
}

class Rename {
	Register original;
	Register renamed;

	public Rename(Register orig, Register ren) {
		original = orig;
		renamed = ren;
	}
}
